home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / terms / kermit / d / pe7mai.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-16  |  20.1 KB  |  723 lines

  1. /* pe7mai.c */
  2. /*
  3.  *    K e r m i t  File Transfer Utility
  4.  *
  5.  *    UNIX Kermit, Columbia University, 1981, 1982, 1983
  6.  *    Bill Catchings, Bob Cattani, Chris Maio, Frank da Cruz, Alan Crosswell
  7.  *
  8.  *    Also:   Jim Guyton, Rand Corporation
  9.  *        Walter Underwood, Ford Aerospace
  10.  *
  11.  * usage    kermit -s [-f -d -i -u -t -p -l -b] file ...    to send files
  12.  *            kermit -r [-d -i -u -t -p -l -b]            to receive files
  13.  *            kermit -g [-f -d -i -u -t -p -l -b] file ...    to get files
  14.  *            kermit -f [-d -t -p -l]                    to send finish command
  15.  *            kermit -x [-d -v -i -u -t -p -l]            to set server mode
  16.  *    where    s=send <flag>, r=receive <flag>, x=server <flag>,
  17.  *            f=finish mode <flag>, g=get files mode <flag>,
  18.  *            d=debug level <number>, v=verbose mode <flag>,
  19.  *            i= image mode <flag>, u=no file name conversion <flag>
  20.  *            l=tty line <device>, b=baud rate <speed>,
  21.  *            t=turnaround mode <flag>, p=parity type <char>
  22.  */
  23.  
  24. /*
  25.  *    Modification History:
  26.  *
  27.  *  Version 1.1(0)
  28.  *  December 4, 1986 - Add btobemp to decode other prefixxed packets.
  29.  *                   - Split program into parts to allow compiling on
  30.  *                     machine with minimum memory configuration.
  31.  *                     put in version number (use -v flag)
  32.  *                        Chris Lent (ihnp4!philabs!phri!cooper!chris)
  33.  *  March 85    - Change to use the IDRIS operating system
  34.  
  35.  *  Oct. 17 Included fixes from Alan Crosswell (CUCCA) for IBM_UTS:
  36.  *      - Changed MYEOL character from \n to \r.
  37.  *      - Change char to int in bufill so getc would return -1 on
  38.  *        EOF instead of 255 (-1 truncated to 8 bits)
  39.  *      - Added read() in rpack to eat the EOL character
  40.  *      - Added fflush() call in printmsg to force the output
  41.  *      NOTE: The last three changes are not conditionally compiled
  42.  *        since they should work equally well on any system.
  43.  *
  44.  *      Changed Berkeley 4.x conditional compilation flag from
  45.  *      UNIX4X to UCB4X.
  46.  *      Added support for error packets and cleaned up the printing
  47.  *      routines.
  48.  */
  49. #define KVERSION "Perkin-Elmer 7000 Series 1.1(0) 5 Dec 86"
  50. #define UTEXT    0        /* Set for 8 bit text strings */
  51.  
  52. #include <std.h>        /* Standard UNIX definitions */
  53. #include <sys.h>        /* Idris system subroutines */
  54. /*#include "sgtty.h"        /* Special tty defs */
  55. #include "pe7tty.h"        /* Special tty defs */
  56.  
  57. /* Symbol Definitions */
  58.  
  59. #define BUFSIZE 80        /* A buffer size for I/O */
  60. #define MAXTRY    8        /* Times to retry a packet */
  61. #define SOH        1        /* Start of header */
  62. #define CR        13        /* ASCII Carriage Return */
  63. #define XON        17        /* ASCII xon character */
  64. #define SP        32        /* ASCII space */
  65. #define DEL        127        /* Delete (rubout) */
  66.  
  67. #define MAXPACKSIZ    94    /* Maximum packet size */
  68. #define DEFPACKSIZ    80    /* The default packet size */
  69. #define MAXFNAME 50 /* My maximum for filename length */
  70. #define SPOVER    14        /* The closest I may come to the end of the output
  71.                             buffer */
  72. #define MYTIME    10        /* Seconds after which I should be timed out */
  73. #define MYPAD    0        /* Number of padding characters I will need */
  74. #define MYPCHAR 0        /* Padding character I need (NULL) */
  75. #define MYEOL    '\r'    /* End-Of-Line character I need */
  76. #define MYQUOTE '#'        /* Quote character I will use */
  77. #define DEFQBIN 'Y'        /* I will do binary quoting */
  78. #define MYQBIN    '&'        /* Binary quoting character */
  79. #define DEFCHKT    '1'        /* Default Check sum type */
  80. #define MYCHKT    '1'        /* Check sum type */
  81. #define DEFREPT '~'        /* Repeat character I will use */
  82. #define MYREPT    '~'        /* Repeat character that I need */
  83.  
  84.  
  85.  
  86. #define TRUE    -1        /* Boolean constants */
  87. #define FALSE    0
  88.  
  89.  
  90. /* Macro Definitions */
  91.  
  92. /*
  93.  * tochar: convert a control character to a printable one by adding a space.
  94.  *
  95.  * unchar: undoes tochar.
  96.  *
  97.  * ctl:        converts between control characters and printable characters by
  98.  *            toggling the control bit (ie. ^A becomes A and A becomes ^A).
  99.  */
  100.  
  101. #define tochar(ch)    ((ch) + ' ')
  102. #define unchar(ch)    ((ch) - ' ')
  103. #define ctl(ch)        ((ch) ^ 64)
  104.  
  105. /* Global Variables */
  106.  
  107. /* This is the format for the return packet from the other user */
  108. int
  109.     spsiz {MAXPACKSIZ},    /* Maximum send packet size */
  110.     timint {MYTIME},    /* Timeout for foreign host on sends */
  111.     pad {0};            /* How much padding to send */
  112. TEXT
  113.     padchar {0},        /* Padding character to send */
  114.     eol {MYEOL},        /* End-Of-Line character to send */
  115.     quote {MYQUOTE},    /* Quote character in incoming data */
  116.     qbin {0},            /* binary conversion character */
  117.     chkt {MYCHKT},        /* Checksum type '1','2', or '3' */
  118.     rept {0};            /* Repeat character if repeat supported */
  119.  
  120. int
  121.     size[2] {0},        /* Size of present data in packets */
  122.     empty[2] {0},        /* Packets ok to fill if zero */
  123.     pknum {0},            /* Current packet buffer index */
  124.     n {0},                /* Packet number */
  125.     nxo {0},            /* Output packet counter for display */
  126.     nxi {0},            /* Nak packet counter for display */
  127.     nxs {0},            /* Saved nak counter */
  128.     repeat_count {0},    /* Repeat counter for repeated characters */
  129.     numtry {0},            /* Times this packet retried */
  130.     oldtry {0},            /* Times previous packet retried */
  131.     iflg {0},            /* Indicates to turn on the image mode */
  132.     image {0},            /* -1 means 8-bit mode (driven by iflg) */
  133.     speed {0},            /* baud rate of the link */
  134.     fflg {0},            /* Indicates to send finish command */
  135.     rflg {0},            /* Indicates receive mode */
  136.     sflg {0},            /* Indicates send mode */
  137.     xflg {0},            /* Indicates server mode */
  138.     gflg {0},            /* Indicates get file mode */
  139.     vflg {0},            /* Verbose messages in server mode */
  140.     tflg {0},            /* Turn around flag */
  141.     pflg {0},            /* What kind of parity are we using? */
  142.     spflg {0},            /* This is our start-up parity flag */
  143.     debug {0},            /* indicates level of debugging output (0=none) */
  144.     filnamcnv {0},        /* -1 means do file name case conversions */
  145.     filecount {0};        /* Number of files left to send */
  146.  
  147. TEXT
  148.     state {0},            /* Present state of the automaton */
  149.     rqbin {0},            /* 8 bit quote character saved in rpar */
  150.     sqbin {0},            /* 8 bit quote character used in spar */
  151.     rrept {0},            /* Repeat character used in spar */
  152.     **filelist {0},        /* List of files to be sent */
  153.     *filnam {0},        /* Current file name */
  154.     *files[10] {0},        /* Pointers for the server file names */
  155.     filename_buffer[MAXPACKSIZ] {0}; /* Buffer for the server file name */
  156. TEXT
  157.     recpkt[MAXPACKSIZ] {0}, /* Receive packet buffer */
  158.     *packet[2] {0},        /* Packet pointers */
  159.     packet0[MAXPACKSIZ] {0}, /* Send packet zero buffer */
  160.     packet1[MAXPACKSIZ] {0}; /* Send packet one buffer */
  161.  
  162. FILE    ttyfd {0};        /* File descriptor of tty for I/O, 0 if remote */
  163.  
  164. FIO *fd {0};            /* pfio pointer */
  165. FIO    pfio {0};            /* Buffer structure for the files */
  166.  
  167. struct tty
  168.         ttymode {0},    /* tty raw mode */
  169.         savemode {0};    /* tty cooked mode */
  170.  
  171. struct {
  172.     int files;            /* Number of files */
  173.     int fc;                /* Number of characters in files */
  174.     int pli;            /* Number of packets received */
  175.     int plo;            /* Number of packets sent */
  176.     int cli;            /* Number of characters received */
  177.     int clo;            /* Number of characters sent */
  178.     ULONG time;            /* Total time for transaction */
  179.   } total {0}, file {0};
  180.  
  181. /*
  182.  *    m a i n
  183.  *
  184.  *    Main routine - parse command and options, set up the
  185.  *    tty lines, and dispatch to the appropriate routine.
  186.  *
  187.  */
  188.  
  189. main(argc,argv)
  190. int argc;                /* Character pointers to and count of */
  191. char **argv;            /* command line arguments */
  192.  
  193. {
  194.     TEXT *ttyname,        /* tty name for LINE argument */
  195.     *cp;                /* char pointer */
  196.  
  197.     printf("IDRIS Kermit - %s",KVERSION);
  198.     if (argc < 2)        /* Make sure there's a command line */
  199.         Usage("Invalid command line - Not enough arguments.");
  200.     packet[0] = &packet0;    /* Set up the packet pointers */
  201.     packet[1] = &packet1;
  202.  
  203.     /* Turn off the parse flags */
  204.     sflg = FALSE;
  205.     rflg = FALSE;
  206.     xflg = FALSE;
  207.     gflg = FALSE;
  208.     fflg = FALSE;
  209.     image = iflg = FALSE;
  210.     filnamcnv = TRUE;    /* conversion for UNIX systems */
  211.     vflg = FALSE;        /* Turn off verbose flags */
  212.     debug = FALSE;        /* Turn off the debug mode */
  213.     ttyname = 0;        /* We did not get a line assignment (pointer) */
  214.     speed = FALSE;        /* Speed not indicated */
  215.     spflg = pflg = FALSE;        /* Parity is not indicated */
  216.     tflg = FALSE;        /* No turn around character */
  217.  
  218.     sqbin = DEFQBIN;    /* Set up default qbin character */
  219.     rqbin = sqbin;    
  220.     qbin = FALSE;
  221.  
  222.     /* Reset the display counters */
  223.     nxo = 0;
  224.     nxi = 0;
  225.     nxs = -1;
  226.  
  227.     getflags(&argc,&argv,\
  228.         "s,r,x,g,f,i,u,v,d#,l*,b#,p?,t:F <file>",\
  229.         &sflg, &rflg, &xflg, &gflg, &fflg, &iflg, &filnamcnv, &vflg,\
  230.         &debug, &ttyname, &speed, &pflg, &tflg);
  231.  
  232.     if (!ttyname)            /* If LINE was not specified, use default */
  233.         ttyname = "/dev/lnk0";
  234.     ttyfd = open(ttyname, UPDATE, 0);/* Open the tty line */
  235.     if (ttyfd <= 0)
  236.         Usage("Cannot open %s.",ttyname);
  237.     
  238.     /* Put the proper tty into the correct mode */
  239.     egtty(ttyfd,&savemode); /* save for later use */
  240.     egtty(ttyfd,&ttymode);    /* set for changing the setup */
  241.  
  242.         printf("IDRIS Kermit - %s",KVERSION);
  243.     vflg = vflg ? vflg : fflg || gflg || rflg || sflg || debug ?
  244.          TRUE : FALSE;
  245.  
  246.     if ((gflg + xflg + rflg + sflg) != 1)    /* Only one command allowed */
  247.         if (!fflg)
  248.             Usage("Only one command allowed - g ! r ! s ! x.");
  249.  
  250.     if (fflg && (xflg || rflg))
  251.         Usage("Finish with server or receive?");
  252.  
  253.     if (!pflg)                /* Do we set up the parity? */
  254.     {
  255.         /* Check for raw mode and if true then force no parity */
  256.         if (ttymode.t_mode & M_RAW) pflg = FALSE;
  257.         else
  258.         {
  259.             /* What has the caller set into the hardware */
  260.             switch (ttymode.t_mode & (M_EVEN | M_ODD))
  261.             {
  262.             case M_ODD:
  263.                 pflg = 'o';
  264.                 break;
  265.             case M_EVEN:
  266.                 pflg = 'e';
  267.                 break;
  268.             case M_EVEN | M_ODD:
  269.                 pflg = 'm';
  270.                 break;
  271.             case 0:
  272.                 pflg = 's';
  273.             }
  274.         }
  275.     }
  276.     else
  277.     {
  278.         if (scnbuf("neoms",5,pflg) == 5)
  279.             Usage("Improper parity call out.");
  280.         if (pflg == 'n') pflg = FALSE;    /* If no parity then set it */
  281.     }
  282.     spflg = pflg;        /* Set up start-up parity */
  283.  
  284.     /* Put the hardware into raw mode */
  285.     ttymode.t_mode = (M_RAW | M_ALL | MR_XON);
  286.  
  287.     if (speed)            /* Do we set up the speed? */
  288.     {
  289.         switch (speed)
  290.         {
  291.             case 110:
  292.                 speed = B110;
  293.                 ttymode.t_mode |= M_2STOP;
  294.                 break;
  295.             case 150:
  296.                 speed = B150;
  297.                 break;
  298.             case 300:
  299.                 speed = B300;
  300.                 break;
  301.             case 1200:
  302.                 speed = B1200;
  303.                 break;
  304.             case 2400:
  305.                 speed = B2400;
  306.                 break;
  307.             case 4800:
  308.                 speed = B4800;
  309.                 break;
  310.             case 9600:
  311.                 speed = B9600;
  312.                 break;
  313.             default:
  314.                 Usage("Bad line speed.");
  315.         }
  316.         ttymode.t_ispeed = speed;
  317.         ttymode.t_ospeed = speed;
  318.     }
  319.     /* Set up the time-out and buffer size */
  320.     ttymode.t_min = 128;
  321.     ttymode.t_time = MYTIME * 10;
  322.     if (tflg)                /* Turn around flag on? */
  323.         ttymode.t_cgo = NULL;    /* Turn off XON in XON/XOFF */
  324.  
  325.     estty(ttyfd,&ttymode);    /* Put asg'd tty in requested mode */
  326.  
  327.     /* All set up, now execute the command that was given. */
  328.  
  329.     if (filnamcnv > 0)    /* Do we want to do file name conversions? */
  330.         filnamcnv = FALSE;
  331.  
  332.     if (iflg)            /* Turn on the image mode? */
  333.     {
  334.         image = TRUE;
  335.         /* Test the parity and make a determination of the qbin
  336.             mode info */
  337.         if (pflg)            /* Pflg contains the parity bit if set */
  338.             sqbin = MYQBIN;        /* Set 8-bit quoting */
  339.         else
  340.             sqbin = DEFQBIN;    /* We can do 8 bit transfers */
  341.     }
  342.  
  343.     if (debug)
  344.     {
  345.         printf("Main 1: S=%d, R=%d, X=%d, G=%d,", sflg, rflg, xflg, gflg);
  346.         printf(" F=%d, I=%d, U=%d, V=%d,", fflg, iflg, filnamcnv, vflg);
  347.         printf(" D=%d\n", debug);
  348.         printf("        L=%s, B=%d, P=%c,", ttyname, speed, pflg);
  349.         printf(" T=%d\n", tflg);
  350.         printf("Main 2: Bits for ttyfd %x\n",ttymode.t_mode);
  351.     }
  352.     if (gflg || sflg)
  353.     {
  354.         /* Anything to get or send? */
  355.         if (argc--)
  356.             filnam = *argv++;    /* Get file to send */
  357.         else
  358.         {
  359.             savemode.t_time = 0;
  360.             estty(ttyfd,&savemode); /* restore the old mode */
  361.             Usage("File name required.");
  362.                                 /* and give error */
  363.         }
  364.         fd = NULL;        /* Indicate no file open yet */
  365.         filelist = argv;    /* Set up the rest of the file list */
  366.         filecount = argc;    /* Number of files left to get or send */
  367.     }
  368.  
  369.     dostat(1);
  370.  
  371.     if (gflg)        /* Get command */
  372.     {
  373.         if (debug) printf("Main 3: Get command\n");
  374.         if (getsw() == FALSE)
  375.             Usage("Get failed.");
  376.         else
  377.             printmsg("Get done.");
  378.     }
  379.  
  380.     if (sflg)        /* Send command */ 
  381.     {
  382.         if (debug) printf("Main 4: Send command\n");
  383.         if (sendsw() == FALSE)    /* Send the file(s) */
  384.             Usage("Send failed.");    /* Report failure */
  385.         else            /*    or */
  386.             printmsg("Send done.");        /* success */
  387.     }
  388.     /* end of sflg */
  389.  
  390.     if (rflg)            /* Receive command */
  391.     {
  392.         if (debug) printf("Main 5: Receive command\n");
  393.         if (debug < 3)
  394.         {
  395.             if (recsw() == FALSE)    /* Receive the file(s) */
  396.                 Usage("Receive failed.");
  397.             else            /* Report failure */
  398.                 printmsg("Receive done.");    /* or success */
  399.         }
  400.         /* End of test for no receive of data (debug < 3) */
  401.     }
  402.     /* End of (rflg) test */
  403.  
  404.     if (xflg) 
  405.         while (server() == TRUE);
  406.  
  407.     if (fflg) 
  408.     {
  409.         if (debug) printf("Main 6: Finish command\n");
  410.             if (finishsw() == FALSE)
  411.                 Usage("Finish failed.");
  412.             else
  413.                 printmsg("Finish done.");
  414.     }
  415.  
  416.     if (vflg)
  417.         if(total.files > 1)
  418.         {
  419.             printf("%d Files\n", total.files);
  420.             printf("%d Bytes   %d Seconds   %d/%d Packets",
  421.                 total.fc, total.time, total.plo, total.pli);
  422.             printf("   %d/%d Characters\n", total.clo, total.cli);
  423.         }
  424.  
  425.     /* Restore the tty (reset the timeout to infinite) */
  426.     savemode.t_time = 0;
  427.     estty(ttyfd,&savemode);
  428.     exit(YES);
  429. }
  430.  
  431. /*
  432.  *    s e n d s w
  433.  *
  434.  *    Sendsw is the state table switcher for sending files.  It loops until
  435.  *    either it finishes, or an error is encountered.    The routines called
  436.  *    by sendsw are responsible for changing the state.
  437.  *
  438.  */
  439.  
  440. sendsw()
  441. {
  442.     TEXT sinit(), sfile(), sdata(), seof(), sbreak();
  443.  
  444.     n = 0;                    /* Initialize message number */
  445.     numtry = 0;                /* Say no tries yet */
  446.     state = 'S';            /* Send initiate is the start state */
  447.     while(TRUE)                /* Do this as long as necessary */
  448.     {
  449.         if (debug) printf("Sendsw 1: State: %c\n",state);
  450.         switch(state)
  451.         {
  452.         case 'S':    state = sinit();    break; /* Send-Init */
  453.         case 'T':    state = sfile();    break; /* Send-File */
  454.         case 'E':    state = sdata();    break; /* Send-Data */
  455.         case 'Z':    state = seof();    break; /* Send-End-of-File */
  456.         case 'B':    state = sbreak(); break; /* Send-Break */
  457.         case 'C':    return (TRUE);        /* Complete */
  458.         case 'A':                         /* "Abort" */
  459.         default:    return (FALSE);    /* Unknown, fail */
  460.         }
  461.     }
  462. }
  463.  
  464. /*
  465.  *    r e c s w
  466.  *
  467.  *    This is the state table switcher for receiving files.
  468.  *
  469.  */
  470.  
  471. recsw()
  472. {
  473.     TEXT rinit(), rfile(), rdata(); /* Use these procedures */
  474.  
  475.     n = 0;                    /* Initialize message number */
  476.     numtry = 0;                /* Say no tries yet */
  477.     state = 'R';            /* Receive-Init is the start state */
  478.     while(TRUE)
  479.     {
  480.         if (debug) printf("Recsw 1: state: %c\n",state);
  481.         switch(state)            /* Do until done */
  482.         {
  483.         case 'R':    state = rinit(); break; /* Receive-Init */
  484.         case 'F':    state = rfile(); break; /* Receive-File */
  485.         case 'D':    state = rdata(); break; /* Receive-Data */
  486.         case 'C':    return (TRUE);        /* Complete state */
  487.         case 'A':
  488.         default:    return (FALSE);        /* "Abort" state */
  489.         }
  490.     }
  491. }
  492.  
  493. /*
  494.  * g e t s w
  495.  *
  496.  * Get a file from the other end
  497.  *
  498.  */
  499.  
  500. getsw()
  501. {
  502.     TEXT ginit(), iinit(), rfile(), rdata(); /* Use these procedures */
  503.     TEXT filnam1[MAXFNAME],
  504.     *newfilnam,
  505.     *cp;
  506.     int num, len;
  507.  
  508.     cpystr(filnam1, filnam, NULL);    /* Copy file name */
  509.     newfilnam = cp = filnam1;
  510.     while (*cp != '\0')
  511.         if (*cp++ == '/')
  512.             newfilnam = cp;
  513.     if (filnamcnv)            /* Convert lower case to upper */
  514.         for (cp = newfilnam; *cp != '\0'; cp++)
  515.             *cp = toupper(*cp);
  516.     len = cp - newfilnam;
  517.     printmsg("Requesting %s as %s",filnam, newfilnam);
  518.     n = 0;                    /* Initialize message number */
  519.     numtry = 0;                /* Say no tries yet */
  520.     state = 'S';
  521.     while (TRUE)
  522.     {
  523.         if (debug) printf("Getsw 1: State: %c\n",state);
  524.         switch (state)
  525.         {
  526.         case 'S':    state = iinit(); break; /* Try this */
  527.         /* Then this */
  528.         case 'R':    state = ginit(len,newfilnam); break;
  529.         case 'F':    state = rfile(); break;    /* Fetch file name */
  530.         case 'D':    state = rdata(); break;    /* Fetch the data */
  531.         case 'C':    return (TRUE);    /* End it all goodly */
  532.         case 'A':
  533.         default:    return (FALSE);    /* End it all badly */
  534.         }
  535.     }
  536. }
  537.  
  538. /*
  539.  *    s e r v e r
  540.  *
  541.  *    This is the state table switcher for the server mode
  542.  *
  543.  */
  544.  
  545. server()
  546. {
  547.     TEXT xinit(), rfile(), rdata(); /* Use these procedures */
  548.     TEXT sinit(), xfile(), sdata(), seof(), sbreak(); /* and these */
  549.  
  550.     image=iflg;
  551.     pflg=spflg;
  552.     n = 0;                    /* Initialize message number */
  553.     numtry = 0;                /* Say no tries yet */
  554.     state = 'X';            /* Begin is the start state */
  555.     while(TRUE)
  556.     {
  557.         if (debug) printf("Server 1: state: %c\n",state);
  558.         switch(state)            /* Do until done */
  559.         {
  560.         case 'X':    state = xinit(); break;    /* Fetch what to do */
  561.         case 'S':    state = sinit(); break;    /* Send init packets */
  562.         case 'T':    state = xfile(); break;    /* maybe open file */
  563.         case 'E':    state = sdata(); break;    /* Send the data */
  564.         case 'Z':    state = seof(); break;
  565.         case 'B':    state = sbreak(); break;
  566.         case 'F':    state = rfile(); break; /* Receive-File */
  567.         case 'D':    state = rdata(); break; /* Receive-Data */
  568.         case 'C':    return (TRUE);            /* Complete state */
  569.         case 'G':    return (FALSE);            /* Finish command */
  570.         case 'A':
  571.         default:    return (debug ? FALSE : TRUE);
  572.         }
  573.     }
  574. }
  575.  
  576. /*
  577.  *    f i n i s h s w
  578.  *
  579.  *    finishsw is the state table switcher for sending general commands
  580.  * It loops until
  581.  *    either it finishes, or an error is encountered.    The routines called
  582.  *    by finishsw are responsible for changing the state.
  583.  *
  584.  */
  585.  
  586. finishsw()
  587. {
  588.     TEXT sfinish();
  589.     n = 0;                    /* Initialize message number */
  590.     numtry = 0;                /* Say no tries yet */
  591.     state = 'F';            /* Send finish is the start state */
  592.     while(TRUE)                /* Do this as long as necessary */
  593.     {
  594.         if (debug) printf("Finishsw 1: State: %c\n",state);
  595.         switch(state)
  596.         {
  597.         case 'F':    state = sfinish();    break; /* Send-Finish command */
  598.         case 'C':    return (TRUE);        /* Complete */
  599.         case 'A':                        /* "Abort" */
  600.         default:    return (FALSE);        /* Unknown, fail */
  601.         }
  602.     }
  603. }
  604.  
  605. /*
  606.  *    i i n i t
  607.  *
  608.  *    Initiate: send this host's parameters and get other side's back.
  609.  *
  610.  */
  611.  
  612. TEXT iinit()
  613. {
  614.     int num, len, slen;            /* Packet number, length */
  615.  
  616.     if (numtry++ > 2) return ('R'); /* If too many tries, give up */
  617.     slen = spar(packet0);        /* Fill up init info packet */
  618.  
  619.     flushinput();            /* Flush pending input */
  620.  
  621.     eol = MYEOL;            /* Preset to my eol character */
  622.     spack('I',n,slen,packet0); /* Send an I packet */
  623.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  624.     {
  625.  
  626.     case 'Y':                /* ACK */
  627.         if (n != num)        /* If wrong ACK, stay in S state */
  628.         {                    /* Wrong packet number */
  629.     case 'N':                /* NAK, Try it again */
  630.     case FALSE:
  631.             nxi++;
  632.             return (state);
  633.         }
  634.         if (!rpar(recpkt,&len))    /* Get the other side's init data */
  635.             return ('A');        /* error with the packet parameters */
  636.  
  637.  
  638.         nxtpkt();
  639.         n = 0;                /* Reset packet number to zero */
  640.         return ('R');        /* OK, switch state to R */
  641.  
  642.     case 'E':                /* Error packet received */
  643.         prerrpkt(recpkt);    /* Print it out and */
  644.     default:
  645.          return ('A');        /* Anything else, just "abort" */
  646.     }
  647.  }
  648.  
  649. /*
  650.  *    s i n i t
  651.  *
  652.  *    Send Initiate: send this host's parameters and get other side's back.
  653.  */
  654.  
  655. TEXT sinit()
  656. {
  657.     int num, len, slen;            /* Packet number, length */
  658.  
  659.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries, give up */
  660.     slen = spar(packet0);        /* Fill up init info packet */
  661.  
  662.     flushinput();            /* Flush pending input */
  663.  
  664.     eol = MYEOL;            /* Preset to my eol character */
  665.     spack('S',n,slen,packet0); /* Send an S packet */
  666.     switch(rpack(&len,&num,recpkt)) /* What was the reply? */
  667.     {
  668.  
  669.     case 'Y':                /* ACK */
  670.         if (n != num)        /* If wrong ACK, stay in S state */
  671.         {                    /* Wrong packet number */
  672.     case 'N':                /* NAK, Try it again */
  673.     case FALSE:
  674.             nxi++;
  675.             return (state);
  676.         }
  677.         if (!rpar(recpkt,&len))    /* Get the other side's init data */
  678.             return ('A');        /* error with the packet parameters */
  679.  
  680.  
  681.         nxtpkt();
  682.         return ('T');        /* OK, switch state to T */
  683.  
  684.     case 'E':                /* Error packet received */
  685.         prerrpkt(recpkt);    /* Print it out and */
  686.     default:
  687.          return ('A');        /* Anything else, just "abort" */
  688.     }
  689.  }
  690.  
  691. /*
  692.  *    r i n i t
  693.  *
  694.  *    Receive Initialization
  695.  */
  696.     
  697. TEXT rinit()
  698. {
  699.     int len, num, slen;            /* Packet length, number */
  700.  
  701.     if (numtry++ > MAXTRY) return ('A'); /* If too many tries, "abort" */
  702.  
  703.     switch(rpack(&len,&num,recpkt)) /* Get a packet */
  704.     {
  705.     case 'S':            /* Send-Init packet */
  706.         if (!rpar(recpkt,&len))    /* Get the other side's init data */
  707.             return ('A');        /* error with the packet parameters */
  708.         slen = spar(packet0);    /* Fill up packet with my init info */
  709.         spack('Y',n,slen,packet0); /* ACK with my parameters */
  710.         oldtry = numtry;    /* Save old try count */
  711.         nxtpkt();
  712.         return ('F');        /* Enter File-Receive state */
  713.  
  714.     case FALSE:            /* Didn't get packet */
  715.         nxi++;
  716.         spack('N',n,0,0);    /* Return a NAK */
  717.         return (state);        /* Keep trying */
  718.  
  719.     case 'E':            /* Error packet received */
  720.         prerrpkt(recpkt);    /* Print it out and */
  721.     default:
  722.         return ('A');        /* Some other packet type, "abort" */
  723.     }
  724. }
  725. /* pe7mai.c End-of-file */
  726.